package it.unipg.bipod.web;

import java.util.Vector;

import it.unipg.bipod.applicationLogic.*;
import it.unipg.bipod.dataModel.*;

/**
 * SegretarioSegretariBean gestisce le attivita' della segreteria collegate alla gestione dei segretari.<br>
 * Permette di consultare l'elenco dei segretari, di modificarne i dati,
 * di creare nuovi segretari o di registrarli a BiPoD.<br>
 * E' presente la sottoclasse pubblica SegretarioBean.<br>
 * Eventuali messaggi o errori vengono segnalati mediante i metodi forniti da DefaultBean.
 * 
 * @author Lorenzo Porzi
 * @see DefaultBean
 * @see SegretarioBean
 */
public class SegretarioSegretariBean extends DefaultBean {
	private SegretarioApplication application;
	
	private SegretarioDettaglioBean[] segretari; // L'elenco dei segretari di BiPoD
	private SegretarioDettaglioBean segretarioInDettaglio; // Il segretario correntemente visualizzato nel dettaglio
	private SegretarioDettaglioBean nuovoSegretario; // Il segretario in fase di creazione
	
	private int paginaCorrente;
	
	/**
	 * Crea un nuovo SegretarioSegretariBean collegato ad una {@link SegretarioApplication}.<br>
	 * L'elenco dei segretari viene caricato immediatamente dal database.
	 * 
	 * @param application la {@link SegretarioApplication} da utilizzare con questo SegretarioSegretariBean.
	 */
	public SegretarioSegretariBean(SegretarioApplication application) {
		super();
		
		this.application = application;
		
		segretarioInDettaglio = null;
		nuovoSegretario = null;
		
		paginaCorrente = 1;
		
		// Carica i docenti
		caricaSegretari();
	}
	
	public int getPaginaCorrente() {
		return paginaCorrente;
	}
	
	public void setPaginaCorrente(int paginaCorrente) {
		this.paginaCorrente = paginaCorrente;
	}
	
	public Vector<Integer> getPagine() {
		Vector<Integer> out = new Vector<Integer>();
		
		for (int i = 0; i < getNumeroPagine(); ++i)
			out.add(i + 1);
		
		return out;
	}
	
	/* --------------------------------
	 * Metodi per l'estrazione dei dati
	 * -------------------------------- */
	
	/**
	 * @return un array di {@link SegretarioDettaglioBean} con la pagina selezionata dell'elenco dei segretari.
	 */
	public SegretarioDettaglioBean[] getSegretari() {		
		if (paginaCorrente >= 1 && paginaCorrente <= getNumeroPagine())
			return getPagina(paginaCorrente); // Ritorna la pagina selezionata
		else
			return getPagina(1); // Ritorna la prima pagina
	}
	
	/**
	 * @return il numero di pagine di segretari.
	 */
	public int getNumeroPagine() {
		return (int)Math.ceil((double)segretari.length / PAGE_SIZE);
	}
	
	/**
	 * @return il numero di segretari presenti nell'elenco.
	 */
	public int getNumeroSegretari() {
		return segretari.length;
	}
	
	/* -------------------------------------------------
	 * Getters e setters per proprieta' e bean secondari
	 * ------------------------------------------------- */
	
	/**
	 * @return il SegretarioDettaglioBean del segretario osservato in dettaglio.
	 */
	public SegretarioDettaglioBean getSegretarioInDettaglio() {
		return segretarioInDettaglio;
	}
	
	/**
	 * @return il SegretarioDettaglioBean del segretario che si sta creando.
	 */
	public SegretarioDettaglioBean getNuovoSegretario() {
		return nuovoSegretario;
	}
	
	/* ---------------------
	 * Metodi di navigazione
	 * --------------------- */
	
	/**
	 * Imposta un nuovo SegretarioDettaglioBean come nuovoSegretario e va alla pagina di creazione nuovo segretario.
	 * 
	 * @return "/pages/segretario-docente-nuovo"
	 */
	public String goToCreaSegretario() {
		nuovoSegretario = new SegretarioDettaglioBean();
		
		return "/pages/segretario-segretario-nuovo";
	}
	
	/* ------------
	 * Altri metodi
	 * ------------ */

	/**
	 * @return ritorna un array di stringhe contenente "si" e "no", utilizzato per il menu' di selezione
	 * dello stato di attivazione del segretario
	 */
	public String[] getOpzioniAttivazione() {
		String[] opzioni = {"si", "no"};
		
		return opzioni;
	}
	
	/**
	 * Carica la lista dei segretari dal database in una variabile locale.<br>
	 * Gli altri metodi che utilizzano la lista dei segretari accedono alla variabile locale
	 * invece che al database. Ogni metodo che causi aggiornamenti all'elenco dei docenti
	 * deve richiamare caricaSegretari() per aggiornare l'elenco conservato in memoria.
	 */
	private void caricaSegretari() {
		try {
			Segretario[] segretari = application.getSegretari();
			this.segretari = new SegretarioDettaglioBean[segretari.length];
			for (int i = 0; i < segretari.length; ++i)
				this.segretari[i] = new SegretarioDettaglioBean(segretari[i]);
		} catch (ApplicationException e) {
			this.segretari = new SegretarioDettaglioBean[0];
		}
	}
	
	private SegretarioDettaglioBean[] getPagina(int pagina) {
		Vector<SegretarioDettaglioBean> outVector = new Vector<SegretarioDettaglioBean>(PAGE_SIZE);
		
		for (int i = (pagina - 1) * PAGE_SIZE; i < pagina * PAGE_SIZE && i < segretari.length; ++i)
			outVector.add(segretari[i]);
		
		SegretarioDettaglioBean[] out = new SegretarioDettaglioBean[outVector.size()];
		outVector.toArray(out);
		return out;
	}
	
	/**
	 * SegretarioDettaglioBean incapsula un segretario e fornisce funzionalita' aggiuntive.<br>
	 * Permette di modificare i dati di un segretario pre-esistente oppure di creare un segretario nuovo.
	 * 
	 * @author Lorenzo Porzi
	 *
	 */
	public class SegretarioDettaglioBean {
		private Segretario segretario; // Il segretario incapsulato
		private Segretario segretarioOld; // I dati iniziali del segretario (variabile utilizzata per verificare l'effettiva modifica dei dati)
		private Registrazione registrazioneSegretario; // La registrazione del segretario
		
		private boolean inEliminazione = false;
		
		/**
		 * Crea un SegretarioDettaglioBean per un nuovo docente
		 */
		public SegretarioDettaglioBean() {			
			this.segretario = new Segretario();
			registrazioneSegretario = new Registrazione();
		}
		
		/**
		 * Crea un SegretarioDettaglioBean associato ad un segretario esistente.<br>
		 * L'elenco delle richieste viene caricato immediatamente.
		 * 
		 * @param segretario il segretario da associare a questo SegretarioDettaglioBean
		 */
		public SegretarioDettaglioBean(Segretario segretario) {
			this.segretario = segretario;
			
			// Salva i dati iniziali del docente
			this.segretarioOld = new Segretario(
					segretario.getNomeUtente(),
					segretario.getEmail(),
					segretario.getNome(),
					segretario.getCognome(),
					segretario.getPassword());
			
			// Carica la registrazione
			try {
				registrazioneSegretario = application.getRegistrazione(segretario.getNomeUtente());
			} catch (ApplicationException e) {
				
			}
		}
		
		/* -----------------------------------
		 * Getters e setters per le proprieta'
		 * ----------------------------------- */
		
		/**
		 * @return il segretario incapsulato da questo oggetto.
		 */
		public Segretario getSegretario() {
			return segretario;
		}
		
		/**
		 * @return lo stato di attività di questo segretario sottoforma di stringa contenente "si" o "no".
		 */
		public String getAttivo() {
			if (registrazioneSegretario.isAttiva())
				return "si";
			
			return "no";
		}
		
		/**
		 * Imposta lo stato di attivita' di questo segretario.
		 * 
		 * @param attivo una stringa contenente "si" o "no".
		 */
		public void setAttivo(String attivo) {			
			if (attivo.equals("si"))
				registrazioneSegretario.setAttiva(true);
			else if (attivo.equals("no"))
				registrazioneSegretario.setAttiva(false);
		}
		
		/**
		 * @return {@code true} se questo docente è in fase di eliminazione, {@code false} altrimenti.
		 */
		public boolean getInEliminazione() {
			return inEliminazione;
		}
		
		/* ---------------------
		 * Metodi di navigazione
		 * --------------------- */
		
		/**
		 * Imposta questo segretario come segretarioInDettaglio e va alla pagina di dettaglio segretario.
		 * 
		 * @return "/pages/segretario-docente-dettaglio".
		 */
		public String vedi() {
			segretarioInDettaglio = this;
			
			return "/pages/segretario-segretario-dettaglio";
		}
		
		/**
		 * Aggiorna i dati del segretario nel database.<br>
		 * Questo metodo apporta modifiche alla base di dati solamente se rileva un'effettivo cambiamento dei dati
		 * del segretario.
		 * Questo metodo utilizza le seguenti proprieta' di presentation.ini:
		 * <ul>
		 *   <li><b>msgDatiModifica</b>: il messaggio visualizzato quando la modifica riesce.</li>
		 *   <li><b>msgErroreModificaDati</b>: il messaggio visualizzato quando la modifica fallisce.</li>
		 * </ul>
		 */
		public void aggiornaDati() {
			try {
				// Trimma i dati
				segretario.setCognome(segretario.getCognome().trim());
				segretario.setEmail(segretario.getEmail().trim());
				segretario.setNome(segretario.getNome().trim());
				
				// Modifica effettivamente i dati del docente solo se c'è stato qualche cambiamento
				if (!segretario.getNome().equals(segretarioOld.getNome()) || !segretario.getCognome().equals(segretarioOld.getCognome()) ||
						!segretario.getEmail().equals(segretarioOld.getEmail()))
					application.aggiornaSegretario(segretario);
				
				application.impostaStatoAttivazione(registrazioneSegretario, registrazioneSegretario.isAttiva());
				
				addInfoMessage(getSettings().getProperty("msgSegretarioDatiModifica"));
			} catch (ApplicationException e) {
				addWarnMessage(getSettings().getProperty("msgErroreSegretarioModificaDati"));
			}
		}
		
		/**
		 * Crea un nuovo segretario a partire dai dati memorizzati dalla proprieta' segretario di questo oggetto.
		 * Questo metodo utilizza le seguenti proprieta' di presentation.ini:
		 * <ul>
		 *   <li><b>msgSegretarioCreato</b>: il messaggio visualizzato quando la creazione riesce.</li>
		 *   <li><b>msgErroreSegretarioPresente</b>: il messaggio visualizzato quando si tenta di creare un docente
		 *   gia' registrato ai servizi web della facolta'.</li>
		 *   <li><b>msgErroreSegretarioRegistrato</b>: il messaggio visualizzato quando si tenta di creare un docente
		 *   che non ha un accounte dei servizi web della facolta' ma che ha una registrazione nel database di BiPoD.</li>
		 *   <li><b>msgErroreCreazioneSegretario</b>: il messaggio visualizzato quando la creazione fallisce per un motivo sconosciuto.</li>
		 * </ul>
		 */
		public String creaSegretario() {
			try {
				application.nuovoSegretario(segretario);
				
				// Ricarica la lista dei segretari
				caricaSegretari();
				
				addInfoMessage(getSettings().getProperty("msgSegretarioCreato"));
				
				return "/pages/segretario-segretari";
			} catch (StatoDocenteException e) {
				switch (e.getStatoDocente()) {
				case StatoDocenteException.PRESENTE:
					addWarnMessage(getSettings().getProperty("msgErroreSegretarioPresente"));
					break;
				case StatoDocenteException.REGISTRATO:
					addWarnMessage(getSettings().getProperty("msgErroreSegretarioRegistrato"));
				}
				
				return null;
			} catch (ApplicationException e) {
				addWarnMessage(getSettings().getProperty("msgErroreCreazioneSegretario"));
				
				return null;
			}
		}
		
		public void iniziaCancellazione() {
			this.inEliminazione = true;
		}
		
		public void annullaCancellazione() {
			this.inEliminazione = false;
		}
		
		public String confermaCancellazione() {
			try {
				if (inEliminazione)
					application.cancellaSegretario(segretario);
				
				addInfoMessage(getSettings().getProperty("msgCancellazioneSegretarioRiuscita").replaceAll("<0>",
						segretario.getCognome() + " " + segretario.getNome()));
				
				caricaSegretari();
				
				return "/pages/segretario-segretari";
			} catch (ApplicationException e) {
				addWarnMessage(getSettings().getProperty("msgErroreCancellazioneSegretario"));
				this.inEliminazione = false;
				
				return null;
			}
		}
	}
}
